package com.ihr360.job.core.repository.support;

import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.jdbc.support.MetaDataAccessException;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

public enum DatabaseType {
    HSQL("HSQL Database Engine"),
    MYSQL("MySQL"),
    ORACLE("Oracle"),
    H2("H2");

    private static final Map<String, DatabaseType> nameMap;

    static {
        nameMap = new HashMap<String, DatabaseType>();
        for (DatabaseType type : values()) {
            nameMap.put(type.getProductName(), type);
        }
    }

    //A description is necessary due to the nature of database descriptions
    //in metadata.
    private final String productName;

    private DatabaseType(String productName) {
        this.productName = productName;
    }

    public String getProductName() {
        return productName;
    }

    /**
     * Static method to obtain a DatabaseType from the provided product name.
     *
     * @param productName
     * @return DatabaseType for given product name.
     * @throws IllegalArgumentException if none is found.
     */
    public static DatabaseType fromProductName(String productName) {
        if (!nameMap.containsKey(productName)) {
            throw new IllegalArgumentException("DatabaseType not found for product name: [" +
                    productName + "]");
        } else {
            return nameMap.get(productName);
        }
    }

    /**
     * Convenience method that pulls a database product name from the DataSource's metadata.
     *
     * @param dataSource
     * @return DatabaseType
     * @throws MetaDataAccessException
     */
    public static DatabaseType fromMetaData(DataSource dataSource) throws MetaDataAccessException {
        String databaseProductName =
                JdbcUtils.extractDatabaseMetaData(dataSource, "getDatabaseProductName").toString();

        databaseProductName = JdbcUtils.commonDatabaseName(databaseProductName);

        return fromProductName(databaseProductName);
    }
}